<template>
	<div>
		<div class="mb-[10px] flex justify-between items-center">
			<div class="flex">
				<slot name="title"></slot>
				<sports-toggle-group v-if="hasSportsToggle" v-model="tab" />
			</div>
			<betting-filter v-if="isEnum(SportsType, tab) && isPC()" :sportId="tab as SportsType" />
		</div>
		<base-list-plus
			class="min-h-[200px]"
			:auto="false"
			:loading="loading"
			:isFinish="isFinish"
			:isEmpty="!showList.length"
			:error="error"
			:moreText="moreText"
			@load="search"
			@reload="search(true)">
			<div ref="el" class="grid gap-[10px]" :class="colsClass">
				<sports-match v-for="item in showList" :key="item.eventId" :data="item" />
			</div>
		</base-list-plus>
	</div>
</template>

<script lang="ts" setup>
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { BaseListPlus } from '@/components/base'
import { SportsMatch, SportsToggleGroup } from '@/components/sports'
import { BettingFilter } from '@/components/betting'
import { useListCols, useRequest } from '@/hooks'
import { getMatchs } from '@/api/betting'
import { Match } from '@/types'
import { useAppStore, useMatchStore, useSportsStore } from '@/store'
import { MatchStatus, SportsType } from '@/enums'
import { getIndexById, isEnum, isPC, removeById, t } from '@/utils'

const props = defineProps({
	sportId: {
		type: String,
		default: null
	},
	leagueId: {
		type: String
	},
	isLive: {
		type: Boolean,
		default: null
	},
	isLeagueHot: {
		type: Boolean,
		default: false
	},
	isDesc: {
		type: Boolean,
		default: false
	},
	hasSportsToggle: {
		type: Boolean,
		default: true
	},
	subscribeType: {
		type: String,
		default: null
	}
})

const emits = defineEmits(['update:sportId'])

const PAGE_SIZE = 12

const tab = ref<SportsType | string | undefined>()

const matchStore = useMatchStore()
const appStore = useAppStore()
const sportsStore = useSportsStore()

const el = ref(null)

const { colsClass } = useListCols(el)

const moreText = computed(() => t('match.more', [list.value.length, total.value]))

const { run, loading, error, total, isFinish, list } = useRequest<Match>(getMatchs, {
	pageSize: PAGE_SIZE,
	onSuccess: () => {
		matchStore.setList(list.value, props.subscribeType)
	}
})

const showList = computed(() =>
	list.value.filter(
		({ status, isLive, markets }) =>
			status !== MatchStatus.resulted &&
			status !== MatchStatus.closed &&
			!(!isLive && !markets.length)
	)
)

const search = (refresh: boolean = false, pageSize: number = 0) => {
	let lastId = 0
	if (!refresh && list.value.length) {
		lastId = list.value[list.value.length - 1].sortId
	}
	run(
		{
			locale: appStore.lang,
			location: appStore.region,
			oddsStyle: appStore.odds,
			isLive: props.isLive,
			sportIDs: tab.value,
			leagueIDs: props.leagueId,
			isLeagueHot: props.isLeagueHot,
			isDesc: props.isLive,
			pageSize,
			lastId
		},
		{ refresh }
	)
}

// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const eventChange = (data: any) => {
	const { type, eventId, sortId, sportId, leagueId, isLive } = data
	if (type === 'add') {
		addEvent(eventId, sortId, sportId, leagueId, isLive)
	} else if (type === 'delete') {
		removeEvent(eventId)
	} else if (type === 'toLive') {
		if (props.isLive) {
			addEvent(eventId, sortId, sportId, leagueId, true)
		} else {
			removeEvent(eventId)
		}
	}
}

const addEventIDs = new Set()

let timer: any

const addEvent = (
	eventId: string,
	sortId: number,
	sportId: SportsType,
	leagueId: string,
	isLive: boolean
) => {
	if (addEventIDs.has(eventId)) {
		return
	}
	if (!sortId) {
		return
	}
	if (props.isLive !== null && props.isLive !== isLive) {
		return
	}
	if (props.leagueId && props.leagueId !== leagueId) {
		return
	}
	if (tab.value && +tab.value !== +sportId) {
		return
	}
	if (props.isLeagueHot && !sportsStore.isRecommedLeagues(leagueId)) {
		return
	}
	if (list.value.length > PAGE_SIZE) {
		if (props.isLive) {
			if (sortId < list.value[list.value.length - 1].sortId) {
				return
			}
		} else {
			if (sortId > list.value[list.value.length - 1].sortId) {
				return
			}
		}
	}
	addEventIDs.add(eventId)
	timer && clearTimeout(timer)
	timer = setTimeout(() => {
		fetchEvents()
	}, 100)
}

const fetchEvents = async () => {
	try {
		const { data } = await getMatchs({
			eventIDs: [...addEventIDs].toString(),
			locale: appStore.lang,
			oddsStyle: appStore.odds,
			pageSize: 100
		})
		data.list.forEach((item: Match) => {
			addEventIDs.delete(item.eventId)
			for (let i = 0; i < list.value.length; i++) {
				if (getIndexById(list.value, item.eventId, 'eventId') > -1) {
					return
				}
				if (
					(props.isLive && item.sortId > list.value[i].sortId) ||
					(!props.isLive && item.sortId < list.value[i].sortId)
				) {
					list.value.splice(i, 0, item)
					break
				} else if (i === list.value.length - 1) {
					list.value.push(item)
				}
			}
		})
		matchStore.setList(list.value, props.subscribeType)
	} catch {
	} finally {
		if (addEventIDs.size > 0) {
			timer = setTimeout(() => {
				fetchEvents()
			}, 10000)
		}
	}
}

const removeEvent = (eventId: string) => {
	const res = removeById(list.value, eventId, 'eventId')
	if (res && list.value.length < PAGE_SIZE && !loading.value) {
		search(false, PAGE_SIZE - list.value.length)
	}
}

const init = () => {
	// bus.$on(SOCKET_EVENT_CHANGE, eventChange)
}

onBeforeUnmount(() => {
	// bus.$off(SOCKET_EVENT_CHANGE, eventChange)
	timer && clearTimeout(timer)
})

watch(
	() => props.sportId,
	(val) => {
		tab.value = val !== null ? val : SportsType.football
	},
	{ immediate: true }
)

watch(
	() => tab.value,
	(val) => {
		emits('update:sportId', val)
	}
)

watch(
	() => [tab.value, props.leagueId, appStore.lang, appStore.region, appStore.odds],
	() => {
		search(true)
	},
	{ immediate: true }
)

init()
</script>
